
typedef struct {
unsigned short fifo_depth;
unsigned short fifo_read_point;
unsigned short fifo_write_point;
unsigned short fifo_used;
unsigned char   *fifo_data;
} FIFO_STRUCT;

extern void ENTER_CRITICAL(); 
extern void EXIT_CRITICAL(); 

void FIFO_init(FIFO_STRUCT *fifo); 
void FIFO_flush(FIFO_STRUCT *fifo);
unsigned char FIFO_read(FIFO_STRUCT *fifo, unsigned char   *data);
unsigned char FIFO_write(FIFO_STRUCT *fifo, unsigned char   *data);
unsigned short FIFO_get_free_size(FIFO_STRUCT *fifo);
unsigned short FIFO_get_used_size(FIFO_STRUCT *fifo);

void FIFO_init(FIFO_STRUCT * fifo) {
ENTER_CRITICAL();
fifo->fifo_read_point = 0;
fifo->fifo_write_point = 0;
fifo->fifo_used = 0;
FIFO_flush(fifo);
EXIT_CRITICAL();
}

void FIFO_flush(FIFO_STRUCT *fifo) {
unsigned short tmp;
ENTER_CRITICAL();
for (tmp = 0; tmp <= (fifo->fifo_depth) - 1; tmp++) {
fifo->fifo_data[tmp] = 0;
}
EXIT_CRITICAL();
}

unsigned char FIFO_read(FIFO_STRUCT *fifo, unsigned char   *data) {

ENTER_CRITICAL();

if (0 == fifo->fifo_used) {
EXIT_CRITICAL();
return 0;
} else {
fifo->fifo_used--;
*data = fifo->fifo_data[fifo->fifo_read_point];
if (fifo->fifo_read_point == ((fifo->fifo_depth) - 1)) {
fifo->fifo_read_point = 0;
} else {
fifo->fifo_read_point += 1;
}
}
return 1;
}

unsigned char FIFO_write(FIFO_STRUCT *fifo, unsigned char   *data) {
ENTER_CRITICAL();
if (fifo->fifo_used == fifo->fifo_depth) {
EXIT_CRITICAL();
return 0;
} else {
fifo->fifo_data[fifo->fifo_write_point] = *data;
fifo->fifo_used++;
if (fifo->fifo_write_point == (fifo->fifo_depth - 1)) {
fifo->fifo_write_point = 0;
} else {
fifo->fifo_write_point += 1;
}
}
EXIT_CRITICAL();
return 1;
}
unsigned short FIFO_get_free_size(FIFO_STRUCT *fifo) {
return (fifo->fifo_depth - fifo->fifo_used);
}
unsigned short FIFO_get_used_size(FIFO_STRUCT *fifo) {
return fifo->fifo_used;
}

